#ifndef __QUEUE_H__
#define __QUEUE_H__

/*
===============================================================================
    Queue template
    single linked
===============================================================================
*/

namespace inf {

    template< typename Type >
    class QueueNode {
    public:
        QueueNode( void ) { next = NULL; }

        Type *		GetNext( void ) const { return next; }
        void		SetNext( Type *next ) { this->next = next; }

    private:
        Type *		next;
    };

    template< typename Type, QueueNode<Type> Type::*nodePtr >
    class Queue {
    public:
        Queue( void );

        void		Append( Type *element );
        Type *		RemoveFirst( void );

        static void	Test( void );

    private:
        Type *		first;
        Type *		last;
    };

    template< typename Type, QueueNode<Type> Type::*nodePtr >
    Queue<Type,nodePtr>::Queue( void ) {
        first = last = NULL;
    }

    template< typename Type, QueueNode<Type> Type::*nodePtr >
    void Queue<Type,nodePtr>::Append( Type *element ) {
        (element->*nodePtr).SetNext( NULL );
        if ( last ) {
            (last->*nodePtr).SetNext( element );
        } else {
            first = element;
        }
        last = element;
    }

    template< typename Type, QueueNode<Type> Type::*nodePtr >
    Type *Queue<Type,nodePtr>::RemoveFirst( void ) {
        Type *element;

        element = first;
        if ( element ) {
            first = (first->*nodePtr).GetNext();
            if ( last == element ) {
                last = NULL;
            }
            (element->*nodePtr).SetNext( NULL );
        }
        return element;
    }

    template< typename Type, QueueNode<Type> Type::*nodePtr >
    void Queue<Type,nodePtr>::Test( void ) {

        class MyType {
        public:
            QueueNode<MyType> queueNode;
        };

        Queue<MyType,&MyType::queueNode> myQueue;

        MyType *element = new MyType;
        myQueue.Append( element );
        element = myQueue.RemoveFirst();
        delete element;
    }


}   // ::inf

#endif /* !__QUEUE_H__ */
